﻿using gt.framework.Cache;
using gt.framework.Utils;
using System;
using System.Collections.Generic;
using System.Runtime.Caching;

namespace gt.framework.Configuration
{
    public static class ConfigManager
    {
        private static readonly string m_keyPrefix = "configkey_";
        private static ManagerConfigBase DefaultConfigManagerInfo
        {
            get { return CentralManagerConfigCreator.CreatedManagerConfig(); }
        }

        public static string GetAppDataConfigPath<T>() where T : ConfigBase, new()
        {
            ConfigBase tempInstance = new T();
            ManagerConfigBase managerConfigBase = CentralManagerConfigCreator.CreatedManagerConfig();
            return GetAppDataConfigPath(managerConfigBase, tempInstance.GetConfigKey());
        }

        public static string GetAppDataConfigPath(string configKey)
        {
            return GetAppDataConfigPath(DefaultConfigManagerInfo, configKey);
        }

        private static string GetAppDataConfigPath(ManagerConfigBase managerConfig, string configKey)
        {
            string fullPathOrRelativePath = managerConfig.GetConfigPath(configKey);
            if (fullPathOrRelativePath == null) throw new InvalidOperationException(string.Format("ConfigKey '{0}' not exists in config {1}.", configKey, managerConfig.GetType().Name));
            return PathUtils.GetFullPath(fullPathOrRelativePath);
        }

        /// <summary>
        /// 仅仅读取数据，不缓存数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetConfig<T>(string configKey = "") where T : ConfigBase, new()
        {
            string fullPath = string.IsNullOrEmpty(configKey) ? GetAppDataConfigPath<T>() : GetAppDataConfigPath(configKey);
            return InvokeGetConfig<T>(fullPath);
        }
        /// <summary>
        /// 读取数据，并缓存数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetConfigFromCache<T>(string configKey = "") where T : ConfigBase, new()
        {
            if (string.IsNullOrEmpty(configKey)) configKey = (new T()).GetConfigKey();

            string configManagerKey = m_keyPrefix + configKey;
            T instance = CacheManager.Get<T>(configManagerKey);
            if (instance == null)
            {
                lock (typeof(T))
                {
                    instance = CacheManager.Get<T>(configManagerKey);
                    if (instance == null)
                    {
                        string fullPath = GetAppDataConfigPath(configKey);
                        instance = ConfigManager.InvokeGetConfig<T>(fullPath);

                        if (instance == null) return null;

                        CacheManager.Insert<T>(configManagerKey, instance, null,new List<string> { fullPath}, (o) =>
                        {
                            CacheManager.Remove(configManagerKey);
                            instance.ConfigChanged();
                        });
                    }
                }
            }

            return instance;
        }
        
        public static T InvokeGetConfig<T>(string fullPath) where T : class, new()
        {
            return (T)XmlFileUtils.LoadXml(fullPath, typeof(T));
        }
    }
}
